package com.iflytek.iot.okhttp.template;

import com.alibaba.fastjson.JSON;
import com.iflytek.iot.common.utils.JsonFormatUtil;
import com.iflytek.iot.okhttp.utils.UrlTemplateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;
import java.util.function.Consumer;

import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

/**
 * @author yu 2019/3/19.
 */
public class CustomerRestTemplate extends RestTemplate {


    private static final Logger LOGGER = LoggerFactory.getLogger(CustomerRestTemplate.class);

    public CustomerRestTemplate() {
    }

    public CustomerRestTemplate(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    /**
     * @param url
     * @param httpHeadersConsumer
     * @param responseType
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T getForObject(String url, Consumer<HttpHeaders> httpHeadersConsumer, Class<T> responseType,
                              Object... uriVariables) {
        long startTime = System.currentTimeMillis();
        HttpHeaders headers = new HttpHeaders();
        httpHeadersConsumer.accept(headers);
        HttpEntity<Object> requestEntity = new HttpEntity<>(headers);
        this.printCurlLog(url, HttpMethod.GET, headers, null, uriVariables);
        T result = super.exchange(url, HttpMethod.GET, requestEntity, responseType, uriVariables)
                .getBody();
        if (LOGGER.isDebugEnabled()) {
            long endTime = System.currentTimeMillis();
            LOGGER.debug("The  {}  costTime={} ms , response= {}", url, (endTime - startTime), JSON.toJSONString(result));
        }
        return result;
    }

    /**
     * post请求
     *
     * @param url
     * @param httpHeadersConsumer
     * @param request
     * @param responseType
     * @param uriVariables
     * @param <T>
     * @return
     */
    public <T> T postForObject(String url, Consumer<HttpHeaders> httpHeadersConsumer, Object request, Class<T> responseType,
                               Object... uriVariables) {
        long startTime = System.currentTimeMillis();
        HttpHeaders headers = new HttpHeaders();
        httpHeadersConsumer.accept(headers);

        HttpEntity<Object> requestEntity = new HttpEntity<>(request, headers);
        this.printCurlLog(url, HttpMethod.POST, headers, request, uriVariables);
        ResponseEntity<T> exchange = super.exchange(url, HttpMethod.POST,
                requestEntity, responseType, uriVariables);
        T result = exchange.getBody();
        if (LOGGER.isDebugEnabled()) {
            long endTime = System.currentTimeMillis();
            LOGGER.debug("The  {}  costTime={} ms , response= {}", url, (endTime - startTime), JSON.toJSONString(result));
        }
        return result;
    }

    public void printCurlLog(String url, HttpMethod httpMethod, HttpHeaders httpHeaders, Object body, Object... uriVariables) {
        if (!logger.isDebugEnabled()) {
            return;
        }
        String methodName = httpMethod.name();
        StringBuilder logTag = new StringBuilder();
        logTag.append("curl -X ").append(methodName);
        logTag.append(" ").append(UrlTemplateUtils.urlTemplate(url, uriVariables)).append(" ");
        if (!CollectionUtils.isEmpty(httpHeaders)) {
            httpHeaders.forEach((k, v) -> logTag.append(" -H '").append(k).append(": ").append(v.get(0)).append("'"));
        }
        if (Objects.isNull(httpHeaders)) {
            httpHeaders = new HttpHeaders();
        }
        MediaType contentType = httpHeaders.getContentType();
        if (Objects.nonNull(body) && Objects.nonNull(contentType)) {
            switch (contentType.toString()) {
                case APPLICATION_JSON_VALUE:
                case APPLICATION_JSON_UTF8_VALUE:
                    String bodyString = JSON.toJSONString(body);
                    logTag.append(" -d '").append(JsonFormatUtil.formatJson(bodyString)).append("'");
                    break;
                default:
                    break;
            }
        }
        LOGGER.debug(logTag.toString());
    }
}
